package strategy

// 策略模式
// https://refactoringguru.cn/design-patterns/strategy

// Strategy 策略接口声明了某个算法各个不同版本间所共有的操作。上下文会使用该接口来
// 调用有具体策略定义的算法。
type Strategy interface {
	execute(a, b int) float64
}

// ConcreteStrategyAdd 具体策略会在遵循策略基础接口的情况下实现算法。
type ConcreteStrategyAdd struct {
}

func (s *ConcreteStrategyAdd) execute(a, b int) float64 {
	return float64(a + b)
}

type ConcreteStrategySubtract struct {
}

func (s *ConcreteStrategySubtract) execute(a, b int) float64 {
	return float64(a - b)
}

// Context 上下文定义了客户端关注的接口。
type Context struct {
	strategy Strategy
}

// 上下文会维护指向某个策略对象的引用。上下文不知晓策略的具体类。上下
// 文必须通过策略接口来与所有策略进行交互。
// 上下文通常会通过构造函数来接收策略对象，同时还提供设置器以便在运行
// 时切换策略。
func (c *Context) setStrategy(s Strategy) {
	c.strategy = s
}

// 上下文会将一些工作委派给策略对象，而不是自行实现不同版本的算法。
func (c *Context) executeStrategy(a, b int) float64 {
	return c.strategy.execute(a, b)
}
